<?php

namespace EthanZ\LaravelExt\Exceptions;

use EthanZ\LaravelExt\Log\Log;
use EthanZ\LaravelExt\Response\Response as MyResponse;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Throwable;
use Exception;

class Handler extends ExceptionHandler
{


    /**
     * 错误信息
     *
     * @var array
     */
    private array $errorInfo = [
        'code_str'   => '',
        'msg'        => '',
        'error_data' => [],
        'need_log'   => 0,
    ];


    /**
     * Report or log an exception.
     *
     * @param Throwable $e
     *
     * @return void
     *
     * @throws Exception|Throwable
     */
    public function report(Throwable $e): void
    {
        $this->setErrorInfo($e);

        // 记录日志.
        if ($this->errorInfo['need_log']) {
            Log::error($this->errorInfo['error_data']);
        }
    }


    /**
     * 整理错误信息
     *
     * @param Throwable $e
     */
    private function setErrorInfo(Throwable $e): void
    {
        $needLog   = 0;
        $errorData = [
            'file'  => $e->getFile(),
            'line'  => $e->getLine(),
            'msg'   => $e->getMessage(),
            'trace' => $e->getTrace(),
        ];
        if ($e instanceof BaseException || $e instanceof RpcException) {
            $needLog   = 1;
            $codeStr   = $e->codeStr;
            $msg       = $e->getMessage();
            $errorData = $e->errorData;
        } elseif ($e instanceof MethodNotAllowedHttpException || $e instanceof NotFoundHttpException) {
            // miss路由.
            $codeStr = 'BAS_URL_001';
            $msg     = trans('lang.BAS_URL_001');
        } elseif ($e instanceof ModelNotFoundException) {
            // 数据未找到.
            $codeStr = 'BAS_PAM_001';
            $msg     = trans('lang.BAS_PAM_001');
        } elseif ($e->getMessage() === 'Too Many Attempts.') {
            // 请求超频.
            $codeStr = 'BAS_RAT_001';
            $msg     = trans('lang.BAS_RAT_001');
        } else {
            $needLog = 1;
            $codeStr = 'ERROR';
            $msg     = trans('lang.ERROR');
        }

        $this->errorInfo = [
            'code_str'   => $codeStr,
            'msg'        => $msg,
            'error_data' => $errorData,
            'need_log'   => $needLog && (!isset($e->needLog) || $e->needLog) ? 1 : 0,
        ];
    }


    /**
     * Render an exception into an HTTP response.
     *
     * @param Request   $request
     * @param Throwable $e
     *
     * @return object
     *
     * @throws Throwable
     */
    public function render($request, Throwable $e): object
    {
        return MyResponse::statusReturn(
            null,
            $this->errorInfo['code_str'],
            $this->errorInfo['msg'],
            $this->errorInfo['error_data'],
        );
    }
}
